#include "CComplexe.h"
#include <math.h>

CComplexe::CComplexe():m_r(0), m_i(0){}

CComplexe::CComplexe(double real, double ima):m_r(real), m_i(ima)
{}

CComplexe CComplexe::operator+ (const CComplexe& c)const
{
	return CComplexe(c.m_r + m_r, c.m_i + m_i);
}

CComplexe CComplexe::operator- (const CComplexe& c)const
{
	return CComplexe(m_r - c.m_r, m_i - c.m_i);
}

CComplexe CComplexe::operator- (double f)const
{
	return CComplexe(m_r - f, m_i);
}

CComplexe CComplexe::operator- ()const
{
	return CComplexe(-m_r, -m_i);
}

CComplexe CComplexe::operator* (const CComplexe& c)const
{
	return CComplexe(m_r * c.m_r - m_i * c.m_i, m_r * c.m_i + m_i * c.m_r);
}

CComplexe CComplexe::operator* (double f)const
{
	return CComplexe(f * m_r, f * m_i);
}

CComplexe CComplexe::operator/ (double f)const
{
	return CComplexe(m_r / f, m_i / f);
}

void CComplexe::operator/= (double f)
{
	m_r /= f;
	m_i /= f;
}

void CComplexe::operator*= (const CComplexe& c)
{
	m_r = m_r * c.m_r - m_i * c.m_i;
	m_i = m_r * c.m_i + m_i * c.m_r;
}

void CComplexe::operator+= (const CComplexe& c)
{
	m_r += c.m_r;
	m_i += c.m_i;
}

CComplexe CComplexe::operator/ (const CComplexe& c)const
{
	CComplexe denom = c * c.conjugate();
	double fDenom = denom.m_r;

	CComplexe result = *this * c.conjugate();
	result = result / fDenom;
	return result;
}

bool CComplexe::operator==(const CComplexe& c)const
{
	if(m_r == c.m_r && m_i == c.m_i)
		return true;

	return false;
}

bool CComplexe::operator==(float f)const
{
	if(m_r == f && m_i == 0)
		return true;

	return false;
}

double CComplexe::modulus()const
{
	return sqrt(m_r * m_r + m_i * m_i);
}

double CComplexe::modulus2()const 
{
	return m_r * m_r + m_i * m_i;
}

CComplexe CComplexe::squareRoot()const
{
	if(m_i == 0 && m_r == 0)
		return CComplexe();

	if(m_i != 0)
	{
		double m = modulus();
		double s = m_i / fabs(m_i);
		return CComplexe(sqrt((m + m_r) / 2.0), s * sqrt((m - m_r) / 2.0));
	}
	else if(m_r < 0)
		return CComplexe(0, sqrt(fabs(m_r)));
	else
		return CComplexe(sqrt(m_r), 0);
}

CComplexe CComplexe::conjugate()const
{
	return CComplexe(m_r, -m_i);
}

CComplexe CComplexe::inverse()const
{
	return CComplexe(m_r / this->modulus2(), -m_i/this->modulus2());
}

bool CComplexe::isReal()const
{
	if(m_i == 0)
		return true;

	return false;
}

ostream& operator<<(ostream& s, const CComplexe& c)
{
	if(c.m_i < 0)
		s << c.m_r << " - i"<<fabs(c.m_i);
	else
		s << c.m_r << " + i"<<c.m_i;
	return s;
}